package com.supermap.dataservice.grid;

import com.supermap.dataservice.util.Arith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ucar.ma2.Array;
import ucar.nc2.Attribute;
import ucar.nc2.NetcdfFile;
import ucar.nc2.Variable;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.math.BigDecimal;

/**
 * 
 * @ClassName: NetCDFAllUtil 
 * @Description: netcdf文件操作类
 * @author zhoujian
 * @date 2018-1-31
 */
public class NetCDFAllUtil {
	private static Logger logger = LoggerFactory.getLogger(NetCDFAllUtil.class);

	public static void main(String[] args) {
		try {
			NetcdfFile ncfFile = NetcdfFile.open("E:/data/EN_NETCDF_data/20160409/12/cf_sfc_20160409_0.grib1.nc");
			Point2D cellsize = getCellSize(ncfFile);
			System.out.println(cellsize);
		} catch (IOException e) {
			logger.error(e.getMessage(), e);
		}
	}
	/**
	 * 
	 * @Description: 获取文件中的time
	 * @author zhoujian
	 * @return int
	 * @throws
	 */
	public static int getDimTime(NetcdfFile netcdfFile) {
		int t = 0;
		try {
			Variable time = netcdfFile.findVariable("time");
			Array tArray = time.read();
			t = tArray.getInt(0);
		} catch (IOException e) {
			logger.error(e.getMessage(), e);
		}
		return t;
	}

	/**
	 * Rectangle2D数据为地理范围
	 * @author zhoujian
	 * @param ncfile
	 * @return
	 */
	public static Rectangle2D getGeoBounds(NetcdfFile ncfile) {
		Rectangle2D geoBounds = new Rectangle2D.Float();
		try {
			Array lonArray = NetCDFAllUtil.getLon(ncfile).read();
			Array latArray = NetCDFAllUtil.getLat(ncfile).read();
			// left bottom right top
			geoBounds.setRect(lonArray.getFloat(0), latArray.getFloat(0),
					Arith.round(lonArray.getFloat((int) lonArray.getSize() - 1) - lonArray.getFloat(0),3),
					Arith.round(latArray.getFloat((int) latArray.getSize() - 1) - latArray.getFloat(0),3) );
		} catch (IOException e) {
			logger.error(e.getMessage(), e);
		}
		return geoBounds;

	}
	/**
	 * 
	 * @Description: 获取列数
	 * @author zhoujian
	 * @return int
	 * @throws
	 */
	public static int getCols(NetcdfFile ncfile) {
		long cols = 0;
		try {
			cols = NetCDFAllUtil.getLon(ncfile).read().getSize();
		} catch (IOException e) {
			logger.error(e.getMessage(), e);
		}
		return (int) cols;
	}
	/**
	 * 
	 * @Description: 获取行数
	 * @author zhoujian
	 * @return int
	 * @throws
	 */
	public static int getRows(NetcdfFile ncfile) {
		long rows = 0;
		try {
			rows = NetCDFAllUtil.getLat(ncfile).read().getSize();
		} catch (IOException e) {
			logger.error(e.getMessage(), e);
		}
		return (int) rows;
	}
	/**
	 * 
	 * @Description: 获取纬度变量
	 * @author zhoujian
	 * @return Variable
	 * @throws
	 */
	public static Variable getLat(NetcdfFile ncfile) {
		Variable latVar = ncfile.findVariable("latitude");
		return latVar;
	}
	/**
	 * 
	 * @Description: 获取经度变量
	 * @author zhoujian
	 * @return Variable
	 * @throws
	 */
	public static Variable getLon(NetcdfFile ncfile) {
		Variable lonVar = ncfile.findVariable("longitude");
		return lonVar;
	}
	/**
	 * 
	 * @Description: 获取分辨率
	 * @author zhoujian
	 * @return Point2D
	 * @throws
	 */
	public static Point2D getCellSize(NetcdfFile netcdfFile) {
		Variable latVar = getLat(netcdfFile);
		Variable lonVar = getLon(netcdfFile);
		Point2D cellSize = new Point2D.Float();
		try {
			Array lonArray = lonVar.read();
			Array latArray = latVar.read();
			BigDecimal lon1 = new BigDecimal(Float.toString(lonArray.getFloat(1)));
			BigDecimal lon0 = new BigDecimal(Float.toString(lonArray.getFloat(0)));
			BigDecimal lat1 = new BigDecimal(Float.toString(latArray.getFloat(1)));
			BigDecimal lat0 = new BigDecimal(Float.toString(latArray.getFloat(0)));
			float lonsize = lon1.subtract(lon0).floatValue();
			float latSize = lat1.subtract(lat0).floatValue();

			cellSize.setLocation(lonsize, latSize);

		} catch (IOException e) {
			logger.error(e.getMessage(), e);
		}
		return cellSize;

	}
	/**
	 * 
	 * @Description: 获取变量的值
	 * @author zhoujian
	 * @return float[]
	 * @throws
	 */
	public static float[] getValues(String feature, NetcdfFile ncfile) {
		float[] value = null;
		try {
			Variable v = ncfile.findVariable(feature);// feature 大小写敏感
			if (v == null) {
				logger.error(ncfile.getLocation() + "要素：" + feature + "为空！");
				return null;
			}
			Array varArray = v.read();

			String dataType = v.getDataType().toString();
			value = new float[(int) varArray.getSize()];
			if (dataType.equalsIgnoreCase("double")) {
				double[] javaArray = (double[]) varArray.copyTo1DJavaArray();
				for (int i = 0; i < javaArray.length; i++) {
					value[i] = (float) javaArray[i];
				}
			} else if (dataType.equalsIgnoreCase("float")) {
				float[] javaArray = (float[]) varArray.copyTo1DJavaArray();
				for (int i = 0; i < javaArray.length; i++) {
					value[i] = javaArray[i];
				}
			} else if (dataType.equalsIgnoreCase("int")) {
				// int[] javaArray = (int[]) varArray.copyTo1DJavaArray();
				for (int i = 0; i < value.length; i++) {
					value[i] = varArray.getInt(i);
				}
			}
		} catch (Exception e) {
			logger.error("文件" + ncfile.getLocation() + "要素：" + feature + "异常！");
			logger.error(e.getMessage(), e);
		}
		return value;
	}
	/**
	 * 
	 * @Description: 获取要素单位
	 * @author zhoujian
	 * @return String
	 * @throws
	 */
	public static String getUnit(String feature, NetcdfFile ncfile) {
		Variable v = ncfile.findVariable(feature);
		Attribute units = v.findAttribute("units");
		return units.getStringValue();

	}

	/**
	 *  经纬度转墨卡托
	 * @param lx
	 * @param ly
	 * @return
	 */
	public static Point2D lonLat2Mercator(double lx, double ly) {
		Point2D mercator = new Point2D.Double();
		double x = lx * 20037508.34 / 180;
		double y = Math.log(Math.tan((90 + ly) * Math.PI / 360)) / (Math.PI / 180);
		y = y * 20037508.34 / 180;
		mercator.setLocation(x, y);
		return mercator;
	}

	/**
	 *  墨卡托转经纬度
	 * @param mercatorX
	 * @param mercatorY
	 * @return
	 */
	public static Point2D Mercator2lonLat(double mercatorX, double mercatorY) {
		Point2D lonLat = new Point2D.Float();
		double x = mercatorX / 20037508.34 * 180;
		double y = mercatorY / 20037508.34 * 180;
		y = 180 / Math.PI * (2 * Math.atan(Math.exp(y * Math.PI / 180)) - Math.PI / 2);
		lonLat.setLocation(x, y);
		return lonLat;
	}
	/**
	 * 
	 * @Description: 获取层次
	 * @author zhoujian
	 * @return int
	 * @throws
	 */
	public static int getLevel(NetcdfFile ncfile) {
		Variable latVar = ncfile.findVariable("level");
		int level = 0;
		try {
			level = latVar.read().getInt(0);
		} catch (IOException e) {
			logger.error(e.getMessage(), e);
			return -1;
		}
		return level;
	}
}
